use crate::{
    c::{self, C},
    server::Server,
};
use std::{collections::HashMap, io, net::SocketAddr, sync::Arc};
use tokio::{
    io::AsyncWriteExt,
    net::tcp::{OwnedReadHalf, OwnedWriteHalf},
    sync::{mpsc::Sender, Mutex},
};
#[derive(Debug)]
pub struct User {
    pub name: String,
    pub ip: String,
    pub port: u16,
    pub c: c::C<String>,
    pub read: Arc<Mutex<OwnedReadHalf>>,
    pub write: Arc<Mutex<OwnedWriteHalf>>,
}

impl User {
    // 创建新用户
    pub async fn new(
        socket_addr: SocketAddr,
        // 用户连接的 socket 地址
        read: Arc<Mutex<OwnedReadHalf>>,   // 用户读取数据的通道
        write: Arc<Mutex<OwnedWriteHalf>>, // 用户写入数据的通道
    ) -> Self {
        let user = Self {
            name: socket_addr.to_string(),
            ip: socket_addr.ip().to_string(),
            port: socket_addr.port(),
            c: C::new(30),
            // 创建一个容量为 30 的消息通道
            read,
            write: write.clone(),
        };
        user.listen_msg().await; // 开始监听用户的消息
        user // 返回新创建的用户
    }

    // 监听用户的消息
    pub async fn listen_msg(&self) {
        let rx_clone = self.c.rx.clone();
        let conn_clone = self.write.clone();
        tokio::spawn(async move {
            let mut rx = rx_clone.lock().await;
            while let Some(msg) = rx.recv().await {
                let mut conn = conn_clone.lock().await;
                match conn.write_all((msg.clone() + "\n").as_bytes()).await {
                    Err(err) if err.kind() != io::ErrorKind::BrokenPipe => {
                        println!("{:?}", err);
                        return;
                    }
                    Ok(_) => {
                        dbg!("user write ok");
                    }
                    Err(err) => {
                        dbg!("user write err", err);
                        return;
                    }
                }
            }
        });
    }

    // 处理用户的消息
    pub async fn do_msg(
        &self,
        online_map: Arc<Mutex<HashMap<String, Arc<Mutex<User>>>>>, // 在线用户列表
        msg: String,                                               // 用户发送的消息
    ) {
        let msg = msg[1..].to_owned(); // 去掉消息前面的 /
        if msg.eq("who") {
            // 查询在线用户
            self.who(online_map).await;
        } else if msg.len() > 7 && msg[..7].eq("rename|") {
            // 修改用户名
            self.rename(online_map, msg).await
        }
    }

    // 修改用户名
    async fn rename(&self, online_map: Arc<Mutex<HashMap<String, Arc<Mutex<User>>>>>, msg: String) {
        let new_name = msg
            .split("|")
            .collect::<Vec<_>>()
            .get(1)
            .map(|x| x.to_string())
            .unwrap(); // 获取新的用户名
        let map_clone = online_map.clone();
        let mut map = map_clone.lock().await;
        match map.get(&new_name) {
            Some(_) => {
                // 用户名已存在
                self.write
                    .lock()
                    .await
                    .write_all(format!("{} 已经存在\n", new_name).as_bytes())
                    .await
                    .unwrap();
            }
            None => {
                // 用户名不存在，修改用户名
                let user = map.remove(&self.name).unwrap();
                let map_clone = map_clone.clone();
                tokio::spawn(async move {
                    let mut map_lock = map_clone.lock().await;
                    user.lock().await.name = new_name.clone();
                    map_lock.insert(new_name.clone(), user.clone());
                    user.lock()
                        .await
                        .c
                        .tx
                        .send(format!("您已经更新用户名为{}", new_name))
                        .await
                });
            }
        }
    }

    // 查询在线用户
    async fn who(&self, online_map: Arc<Mutex<HashMap<String, Arc<Mutex<User>>>>>) {
        let map = online_map.lock().await;
        for (name, _) in map.iter() {
            let who_msg = format!("{name} 在线\n");
            self.write
                .lock()
                .await
                .write_all(who_msg.as_bytes())
                .await
                .unwrap();
        }
    }

    // 用户下线
    pub async fn off_line(
        user: Arc<Mutex<Self>>,                                    // 下线的用户
        tx: Sender<String>,                                        // 消息通道
        online_map: Arc<Mutex<HashMap<String, Arc<Mutex<User>>>>>, // 在线用户列表
    ) {
        let name = user.lock().await.name.clone();
        let mut map = online_map.lock().await;
        map.remove(&name); // 从在线用户列表中移除用户
        Server::broad_cast(user, tx, "下线了").await; // 广播用户下线消息
    }

    // 用户上线
    pub async fn on_line(
        user: Arc<Mutex<Self>>,                                    // 上线的用户
        tx: Sender<String>,                                        // 消息通道
        online_map: Arc<Mutex<HashMap<String, Arc<Mutex<User>>>>>, // 在线用户列表
    ) {
        let mut map = online_map.lock().await;
        let user_lock = user.lock().await;
        map.insert(user_lock.name.clone(), user.clone()); // 将用户加入在线用户列表
        Server::broad_cast(user.clone(), tx, "上线了").await; // 广播用户上线消息
    }
}
